package Underworld_Survival;


import java.io.Serializable;
import java.util.EnumSet;
import java.util.Map;
import java.util.UUID;

// 定义触发条件枚举
enum BuffTriggerCondition {
    BERORE_BATTLE,    //战斗之前
    AFTER_BATTLE,    //战斗之后
    STAGE_END,       //关卡结束时
    STAGE_BEFORE,    //关卡开始时
    TURN_START,      // 回合开始时触发
    ATTACK_BEFORE,   // 攻击前触发
    ATTACK_AFTER,    // 攻击后触发
    DEFEND_BEFORE,   // 防御前触发
    DEFEND_AFTER,    // 防御后触发
    INJURED_BEFORE,  //受伤之前触发
    INJURED_AFTER,   // 受伤后触发
    TURN_END,        // 回合结束时触发
    HEALED_AFTER,    // 治疗后触发
    SKILL_USE_BEFORE,// 使用技能前触发
    SKILL_USE_AFTER, // 使用技能后触发
    ON_APPLY,        // 施加时立即触发
    ON_REMOVE        // 移除时触发
}

abstract class Buff implements Serializable {
    protected transient String name;//buff名称
    protected transient String effectIntroduction;//buff效果文字介绍
    protected transient int initialDuration; // 初始持续时间
    protected int remainingDuration; // 剩余回合
    protected transient boolean onlyAppliyedOnce;//是否只加成一次
    protected transient boolean effectApplied = false; // 标记是否已应用效果
    protected transient boolean isDebuff;//buff是否是负面效果
    protected transient final EnumSet<BuffTriggerCondition> triggerConditions;//buff触发时间列表，支持多种触发时间
    protected transient Map<AttributeType,Float> buffEffectAttribute;//buff应用时对属性的具体效果（不扣血，不扣能量的buff的属性）
    protected transient EffectManager manager;//记录buff效果，保证能够正确移除
    protected transient String buffEffectId;// 关联的效果ID
    private static final long serialVersionUID = 1L;

    public abstract String getBuffId();

    public Buff(EnumSet<BuffTriggerCondition> triggerConditions, EffectManager manager) {
        this.triggerConditions = triggerConditions;
        this.manager = manager;}
    public Buff(String name, String effectIntroduction, int initialDuration, boolean onlyAppliyedOnce,
                boolean isDebuff, EnumSet<BuffTriggerCondition> triggerConditions){
        this.name=name;
        this.effectIntroduction=effectIntroduction;
        this.initialDuration=initialDuration;
        this.remainingDuration=initialDuration;
        this.onlyAppliyedOnce=onlyAppliyedOnce;
        this.isDebuff=isDebuff;
        this.triggerConditions=triggerConditions;
        this.buffEffectId = UUID.randomUUID().toString();
    }

    //buff应用，触发和移除
    public abstract void onApply(Role role);
    public abstract void onApply(BattleManager BattleCtx);
    public abstract void onTrigger(Role role);
    public abstract void onTrigger(BattleManager BattleCtx);
    public abstract void onExpire(Role role);
    public abstract void onExpire(BattleManager BattleCtx);

    public boolean isExpired(){return remainingDuration==0;}
    public void updateDuration(){if(remainingDuration>0) remainingDuration--;}
    public void refresh() {remainingDuration = initialDuration;}

    //getter,setter
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public String getEffectIntroduction() {return effectIntroduction;}
    public void setEffectIntroduction(String effectIntroduction) {this.effectIntroduction = effectIntroduction;}
    public int getInitialDuration() {return initialDuration;}
    public void setInitialDuration(int initialDuration) {this.initialDuration = initialDuration;}
    public int getRemainingDuration() {return remainingDuration;}
    public void setRemainingDuration(int remainingDuration) {this.remainingDuration = remainingDuration;}
    public boolean isOnlyAppliyedOnce() {return onlyAppliyedOnce;}
    public void setOnlyAppliyedOnce(boolean onlyAppliyedOnce) {this.onlyAppliyedOnce = onlyAppliyedOnce;}
    public boolean isEffectApplied() {return effectApplied;}
    public void setEffectApplied(boolean effectApplied) {this.effectApplied = effectApplied;}
    public boolean isIsDebuff() {return isDebuff;}
    public void setIsDebuff(boolean isDebuff) {this.isDebuff = isDebuff;}
    public EnumSet<BuffTriggerCondition> getTriggerConditions() {return triggerConditions;}

}

//全局buff列表
//1.中毒poison
class poison extends Buff{
    public poison() {
        super("【中毒】", "每回合受到最大生命值10%，共持续4回合（关卡）",
                4,false,true,
                EnumSet.of(BuffTriggerCondition.TURN_END,BuffTriggerCondition.STAGE_END)
        );
    }
    @Override
    public String getBuffId() { return "buff_poison"; }

    @Override
    public void onApply(Role role) {}
    @Override
    public void onTrigger(Role role) {
        int damage = (int)(role.getTotalMaxHP() * 0.1);
        role.reduceHP(damage);
    }
    @Override
    public void onExpire(Role role) {}

    @Override
    public void onApply(BattleManager battleCtx) {}
    @Override
    public void onTrigger(BattleManager battleCtx) {
        int damage = (int)(battleCtx.getAttacker().getTotalMaxHP() * 0.1);
        battleCtx.getAttacker().reduceHP(damage);
    }
    @Override
    public void onExpire(BattleManager battleCtx) {}

}
//2.灼烧burning
class burning extends Buff{
    public burning() {
        super("【灼烧】", "每回合受到最大生命值12%，共持续3回合（关卡）",
                3,false,true,
                EnumSet.of(BuffTriggerCondition.TURN_END,BuffTriggerCondition.STAGE_END)
        );
    }

    @Override
    public String getBuffId() { return "buff_burning"; }

    @Override
    public void onApply(Role role) {}
    @Override
    public void onTrigger(Role role) {
        int damage = (int)(role.getTotalMaxHP() * 0.12);
        role.reduceHP(damage);}
    @Override
    public void onExpire(Role role) {}

    @Override
    public void onApply(BattleManager battleCtx) {}
    @Override
    public void onTrigger(BattleManager battleCtx) {
        int damage = (int)(battleCtx.getAttacker().getTotalMaxHP() * 0.12);
        battleCtx.getAttacker().reduceHP(damage);}
    @Override
    public void onExpire(BattleManager battleCtx) {}
}
//3.沸血boilingBlood
class boilingBlood extends Buff{
    public boilingBlood() {
        super("【沸血】", "增强自身基础攻击力25%，共持续4回合",
                4,true,false,
                EnumSet.of(BuffTriggerCondition.TURN_END,BuffTriggerCondition.ON_APPLY)
        );
        buffEffectId="沸血"+buffEffectId;
    }

    @Override
    public String getBuffId() { return "buff_boilingBlood"; }

    @Override
    public void onApply(Role role) {
        this.manager=role.getEffectManager();
        String effectId=manager.applyEffect(buffEffectId,Map.of(AttributeType.BONUS_STR,
                new FixedValue((float)(role.getBaseStr()*0.25))));
        Map<AttributeType, Float> actualValues = manager.getEffectsById(effectId,role);
        role.modifyAttributes(actualValues,true);
    }
    @Override
    public void onTrigger(Role role) {}// 属性修正型Buff无需每次触发额外操作
    @Override
    public void onExpire(Role role) {
        // 移除效果
        Map<AttributeType, Float> reverse = manager.removeEffects(buffEffectId,role);
        role.modifyAttributes(reverse,true);
    }

    @Override
    public void onApply(BattleManager battleCtx) {
        // 注册效果到攻击者
        this.manager=battleCtx.getAttacker().getEffectManager();
        String effectId=manager.applyEffect(buffEffectId,Map.of(AttributeType.BONUS_STR,
                new FixedValue((float)(battleCtx.getAttacker().getBaseStr()*0.25))));
        Map<AttributeType, Float> actualValues = manager.getEffectsById(effectId,battleCtx.getAttacker());
        battleCtx.getAttacker().modifyAttributes(actualValues,true);
    }
    @Override
    public void onTrigger(BattleManager battleCtx) {}// 属性修正型Buff无需每次触发额外操作
    @Override
    public void onExpire(BattleManager battleCtx) {
        // 移除效果
        Map<AttributeType, Float> reverse = manager.removeEffects(buffEffectId,battleCtx.getAttacker());
        battleCtx.getAttacker().modifyAttributes(reverse,true);
    }

}
//4.金刚adamant
class adamant extends Buff{
    public adamant() {
        super("【金刚】", "增强自身基础防御力25%，共持续4回合（关卡）",
                4,true,false,
                EnumSet.of(BuffTriggerCondition.TURN_END,BuffTriggerCondition.ON_APPLY)
        );
        buffEffectId="金刚"+buffEffectId;
    }

    @Override
    public String getBuffId() { return "buff_adamant"; }

    @Override
    public void onApply(Role role) {
        // 注册效果到攻击者(buff拥有者)
        this.manager=role.getEffectManager();
        String effectId=manager.applyEffect(buffEffectId,Map.of(AttributeType.BONUS_DEF,
                new FixedValue((float)(role.getBaseDef()*0.25))));
        Map<AttributeType, Float> actualValues = manager.getEffectsById(effectId,role);
        role.modifyAttributes(actualValues,true);
    }
    @Override
    public void onTrigger(Role role) {}// 属性修正型Buff无需每次触发额外操作
    @Override
    public void onExpire(Role role) {
        // 移除效果
        Map<AttributeType, Float> reverse = manager.removeEffects(buffEffectId,role);
        role.modifyAttributes(reverse,true);
    }

    @Override
    public void onApply(BattleManager battleCtx) {
        // 注册效果到攻击者(buff拥有者)
        this.manager=battleCtx.getAttacker().getEffectManager();
        String effectId=manager.applyEffect(buffEffectId,Map.of(AttributeType.BONUS_DEF,
                new FixedValue((float)(battleCtx.getAttacker().getBaseDef()*0.25))));
        Map<AttributeType, Float> actualValues = manager.getEffectsById(effectId,battleCtx.getAttacker());
        battleCtx.getAttacker().modifyAttributes(actualValues,true);

    }
    @Override
    public void onTrigger(BattleManager battleCtx) {}// 属性修正型Buff无需每次触发额外操作
    @Override
    public void onExpire(BattleManager battleCtx) {
        // 移除效果
        Map<AttributeType, Float> reverse = manager.removeEffects(buffEffectId,battleCtx.getAttacker());
        battleCtx.getAttacker().modifyAttributes(reverse,true);
    }

}
//5.无敌indomitable
class indomitable extends Buff{
    public indomitable() {
        super("无敌", "免疫所有伤害,持续1回合（关卡）",
                1,false,false,
                EnumSet.of(BuffTriggerCondition.INJURED_BEFORE)
        );
    }

    @Override
    public String getBuffId() { return "buff_indomitable"; }

    //无敌buff只在战斗时生效
    @Override
    public void onApply(Role role) {}
    @Override
    public void onTrigger(Role role) {}
    @Override
    public void onExpire(Role role) {}

    @Override
    public void onApply(BattleManager battleCtx) {battleCtx.setInjuryValue(0);}
    @Override
    public void onTrigger(BattleManager battleCtx) {}
    @Override
    public void onExpire(BattleManager battleCtx) {}

}
//6.焕生revitalize
class revitalize extends Buff{
    public revitalize() {
        super("【焕生】", "每回合恢复最大生命值10%，持续4回合（关卡）",
                4,false,false,EnumSet.of(BuffTriggerCondition.TURN_END,
                        BuffTriggerCondition.STAGE_END)
        );
    }

    @Override
    public String getBuffId() { return "buff_revitalize"; }

    @Override
    public void onApply(Role role){}
    @Override
    public void onTrigger(Role role) {
        int refillValue = (int)(role.getTotalMaxHP() * 0.1);
        role.refillHP(refillValue);}
    @Override
    public void onExpire(Role role) {}

    @Override
    public void onApply(BattleManager battleCtx){}
    @Override
    public void onTrigger(BattleManager battleCtx) {
        int refillValue = (int)(battleCtx.getAttacker().getTotalMaxHP() * 0.1);
        battleCtx.getAttacker().refillHP(refillValue);}
    @Override
    public void onExpire(BattleManager battleCtx) {}

}
//7.诅咒curse
class curse extends Buff{
    public curse() {
        super("【诅咒】", "降低基础力量、防御、速度15%,持续4回合（关卡）",
                4,true,false,
                EnumSet.of(BuffTriggerCondition.TURN_END,BuffTriggerCondition.STAGE_END,
                        BuffTriggerCondition.ON_APPLY)
        );
        buffEffectId="诅咒"+buffEffectId;
    }

    @Override
    public String getBuffId() { return "buff_curse"; }

    @Override
    public void onApply(Role role) {
        // 注册效果到攻击者(buff拥有者)
        this.manager=role.getEffectManager();
        String effectId=manager.applyEffect(buffEffectId,Map.of(AttributeType.BONUS_DEF,new FixedValue(-(float)(role.getBaseDef()*0.15)),
                AttributeType.BONUS_STR,new FixedValue(-(float)(role.getBaseStr()*0.15)),
                AttributeType.BONUS_EP,new FixedValue(-(float)(role.getBaseEP()*0.15))));
        Map<AttributeType, Float> actualValues = manager.getEffectsById(effectId,role);
        role.modifyAttributes(actualValues,true);
    }
    @Override
    public void onTrigger(Role role) {}
    @Override
    public void onExpire(Role role) {
        // 移除效果
        Map<AttributeType, Float> reverse = manager.removeEffects(buffEffectId,role);
        role.modifyAttributes(reverse,true);
    }

    @Override
    public void onApply(BattleManager battleCtx) {
        // 注册效果到攻击者(buff拥有者)
        this.manager=battleCtx.getAttacker().getEffectManager();
        String effectId=manager.applyEffect(buffEffectId,Map.of(AttributeType.BONUS_DEF,new FixedValue(-(float)(battleCtx.getAttacker().getBaseDef()*0.15)),
                AttributeType.BONUS_STR,new FixedValue(-(float)(battleCtx.getAttacker().getBaseStr()*0.15)),
                AttributeType.BONUS_EP,new FixedValue(-(float)(battleCtx.getAttacker().getBaseEP()*0.15))));
        Map<AttributeType, Float> actualValues = manager.getEffectsById(effectId,battleCtx.getAttacker());
        battleCtx.getAttacker().modifyAttributes(actualValues,true);
    }
    @Override
    public void onTrigger(BattleManager battleCtx) {}
    @Override
    public void onExpire(BattleManager battleCtx) {
        // 移除效果
        Map<AttributeType, Float> reverse = manager.removeEffects(buffEffectId,battleCtx.getAttacker());
        battleCtx.getAttacker().modifyAttributes(reverse,true);
    }

}
//8.嗜血bloodthirsty
class bloodthirsty extends Buff{
    public bloodthirsty() {
        super("【嗜血】", "攻击敌人后，吸收伤害值的40%,持续4回合",
                4,false,false,
                EnumSet.of(BuffTriggerCondition.ATTACK_AFTER)
        );
    }

    @Override
    public String getBuffId() { return "buff_bloodthirsty"; }

    //嗜血只在攻击敌人时才触发
    @Override
    public void onApply(Role role) {}
    @Override
    public void onTrigger(Role role) {}
    @Override
    public void onExpire(Role role) {}

    @Override
    public void onApply(BattleManager battleCtx) {}
    @Override
    public void onTrigger(BattleManager battleCtx) {
        int refillValue = (int)(battleCtx.getInjuryValue()* 0.4);
        battleCtx.getAttacker().refillHP(refillValue);}
    @Override
    public void onExpire(BattleManager battleCtx) {}
}
